package com.swdegao.iot.netty.udp.server.channelhandler;

import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.fastjson.JSON;
import com.swdegao.iot.SwdegaoIotMgtServerApplication;
import com.swdegao.iot.netty.entity.HandlerMessage;
import com.swdegao.iot.netty.entity.OnOffData;
import com.swdegao.iot.netty.entity.Parameter;
import com.swdegao.iot.netty.entity.Terminals;
import com.swdegao.iot.netty.service.impl.TerminalsServiceImpl;
import com.swdegao.iot.netty.utils.Const;
import com.swdegao.iot.netty.utils.DataResction;
import com.swdegao.iot.netty.utils.DataValida;
import com.swdegao.iot.netty.utils.RedisUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;

/**
 * @Author:zt
 * @Date: Created in 8:20 2018\10\26 0002
 */

public class ParseMessgaeHandler2 extends SimpleChannelInboundHandler<Object> {

	// 定义一个全局的记录器，通过LoggerFactory获取
	private final static Logger logger = LoggerFactory.getLogger(ParseMessgaeHandler2.class);

	@Autowired
	private RedisUtils redisUtils = SwdegaoIotMgtServerApplication.getBean(RedisUtils.class);
	static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

	private HandlerMessage hm = new HandlerMessage();
	@Autowired
	private TerminalsServiceImpl ts = SwdegaoIotMgtServerApplication.getBean(TerminalsServiceImpl.class);

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { // (4)
		ByteBuf in = (ByteBuf) msg;// 80 23 00 81 383630313934303332393334363036 40 71 0d 0a
		/*byte[] b = ByteBufUtil.getBytes(in);
		System.out.println(new String(b));*/
		ByteBuf bodyAll = in.duplicate();
		String ChannelID = null;
		try {
			if (DataValida.ValidateHead(in.getByte(0))) {// 验证帧头:0x80
				byte[] byteChannel = DataResction.ResctionIMEI(in);
				ChannelID = new String(byteChannel);
				// 更换连接ID
				if (!Const.hasChannelID(ChannelID)) {
					String realChannelID = Const.isChannel(ctx.channel());
					//logger.info("!Const.hasChannelID,realChannelID " +realChannelID);
					Const.ChangeClientId(realChannelID, ChannelID);
					// 记录上线记录
					onoffLineAction(ChannelID, Parameter.online_des,1);// 记录下线
					onoffLineForCenter(ChannelID,1);
				}
				// 检查重复链接ID 不同实例 切换实例
				if (Const.ischangeChannelID(ChannelID, ctx.channel())) {
					logger.info("Const.ischangeChannelID,ChannelID " +ChannelID);
					Const.changeChannel(ChannelID, ctx.channel());
					// 记录重复上线记录
					onoffLineAction(ChannelID, Parameter.reonline_des,0);// 记录下线
					onoffLineForCenter(ChannelID,0);
				}
				// 数据域
				ByteBuf recevieMsg = Unpooled.wrappedBuffer(DataResction.ResctionBody(bodyAll));
				// 数据类型:0x81,0x82,0x83,0x84
				Byte type = DataResction.ResctionDataType(in.getByte(3));
				hm.setActionTpye(type);
				hm.setImei(ChannelID);
				hm.setRecevieMsg(recevieMsg);
				
				// ReferenceCountUtil.release(recevieMsg);
				ctx.fireChannelRead(hm);
			} else {
				// 验证不通过关闭channel
				// ctx.writeAndFlush(CallBackMessage.ERROR.duplicate());
				ctx.close();
			}
		}catch(Exception e){
			logger.error(ChannelID+e.getMessage());
		} finally {
			// ReferenceCountUtil.release(in);
			//logger.error(ChannelID+"ParseMessgaeHandlerfinally");
		}
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception { // (5)
		Channel incoming = ctx.channel();
		Const.add(String.valueOf(UUID.randomUUID()), ctx.channel());
		channels.add(ctx.channel());
		//logger.info("client " + incoming.remoteAddress() + "上线");
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception { // (6)
		String channelId = Const.getChannelIds(ctx.channel());
		onoffLineAction(channelId, Parameter.offline_des,0);// 记录下线
		onoffLineForCenter(channelId,0);
		Const.remove(ctx.channel());
		channels.remove(ctx.channel());
		// 记录下线
		//logger.info("Disconnected client " + ctx.channel().remoteAddress() + "掉线" + channelId);
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (7)
		Channel incoming = ctx.channel();
		//logger.info("client " + incoming.remoteAddress() + "异常" + cause.getMessage());
		// 当出现异常就关闭连接
		cause.printStackTrace();
		// ctx.close();
	}

	/**
	 * 上线操作
	 * 
	 * @param imei
	 * @param channel
	 */
	private void onoffLineAction(String imei, String type,int status) {
		OnOffData onOff = new OnOffData();
		onOff.setImei(imei);
		onOff.setCreatetime(System.currentTimeMillis());
		onOff.setAction(type);
		redisUtils.lPush(imei + Parameter.on_off_info, JSON.toJSONString(onOff));// 存储所有updata数据
	}
	/**
	 * 上线下线操作
	 * 
	 * @param imei
	 * @param channel
	 */
	@SuppressWarnings("unused")
	private void onoffLineForCenter(String imei, int status) {
		Terminals terminal = new Terminals();
		terminal.setImei(imei);
		terminal.setOnlinestatus(status);
		//ts.updateTerminalOnlineStatus(terminal);
	}

}
